﻿#region "Copyright (C) Lenny Granovsky. 2005-2013"
//This program is free software distribute under the terms of the GNU General Public License as published by
//the Free Software Foundation. Please read AssemblyInfo.cs file for more information.
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Web.Enhancements.Rest.Filters
{
    public class AuthorizeFilter : IWebRestFilter
    {
        public bool RequiresAuthorization { get; set; }
        public List<string> Users { get; set; }
        public List<string> Roles { get; set; }

        public AuthorizeFilter()
        {
            this.Roles = new List<string>();
            this.Users = new List<string>();
        }

        /// <summary>
        /// Method that is called prior the REST service handler created. This allows to cancel the call at earlier stages. 
        /// </summary>
        /// <remarks>The session and list parameters are not available at this time.</remarks>
        /// <param name="httpContext">Current HTTP content.</param>
        /// <param name="serviceContext">Current REST service context.</param>
        public void BeforeHandlerCreated(System.Web.HttpContext httpContext, IWebRestServiceContext serviceContext)
        {
            //verify if method requires request validation - validate if should
            if (this.RequiresAuthorization)
            {
                if (!httpContext.Request.IsAuthenticated)
                    throw new WebRestSecurityException(string.Format(ErrorMessages.ResourceManager.GetString("MethodAuthorizationFailed"), serviceContext.MethodInfo.Name, "0"));
                if (this.Users.Count > 0 || this.Roles.Count > 0)
                {
                    if (httpContext.User == null)
                        throw new WebRestSecurityException(string.Format(ErrorMessages.ResourceManager.GetString("MethodAuthorizationFailed"), serviceContext.MethodInfo.Name, "1"));
                    if (httpContext.User.Identity == null)
                        throw new WebRestSecurityException(string.Format(ErrorMessages.ResourceManager.GetString("MethodAuthorizationFailed"), serviceContext.MethodInfo.Name, "2"));
                    if (!httpContext.User.Identity.IsAuthenticated)
                        throw new WebRestSecurityException(string.Format(ErrorMessages.ResourceManager.GetString("MethodAuthorizationFailed"), serviceContext.MethodInfo.Name, "3"));
                    if (this.Roles.Count > 0)
                    {
                        bool found = false;
                        foreach (string role in this.Roles)
                        {
                            if (httpContext.User.IsInRole(role.Trim()))
                            {
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                            throw new WebRestSecurityException(string.Format(ErrorMessages.ResourceManager.GetString("MethodAuthorizationFailed"), serviceContext.MethodInfo.Name, "4"));
                    }
                    if (this.Users.Count > 0)
                    {
                        bool found = false;
                        foreach (string user in this.Users)
                        {
                            if (string.Compare(httpContext.User.Identity.Name, user.Trim(), true) == 0)
                            {
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                            throw new WebRestSecurityException(string.Format(ErrorMessages.ResourceManager.GetString("MethodAuthorizationFailed"), serviceContext.MethodInfo.Name, "5"));
                    }
                }
            }
        }

        public void BeforeMethodCall(System.Web.HttpContext httpContext, IWebRestServiceContext serviceContext)
        {
        }

        public void AfterMethodCall(System.Web.HttpContext context, ref object returnValue)
        {
        }
    }
}
